/************************************************************************************/ /**
*\n  @file       hardwares.cpp
*\n  @brief      硬件设备接口文件
*\n  @details
*\n -------------------------------------------------------------------------
*\n  文件说明：
*\n       1. 硬件设备接口文件
*\n       2. 定义硬件设备接口
*\n       3. C++设计，并提供C接口
*\n
*\n -------------------------------------------------------------------------
*\n  版本:   修改人:   修改日期:       描述:
*\n  V1.0    罗先能    2017.5.3       创建
*\n
****************************************************************************************/

/***************************************************************************************
 * 头文件
****************************************************************************************/
#include <iostream>
// 接口
#include "bus.hpp"
#include "bus_gpio.hpp"
#include "bus_spi.hpp"
// 设备
#include "device_gpio.hpp"
#include "device_uart.hpp"
#include "hardwares.h"

#undef  DEBUG_LEVEL
#define DEBUG_LEVEL 2    // 定义debug级别 (0 ~ 5)
#include "vdebug.h"


using namespace std;

/***************************************************************************************
 * 宏定、常量、结构定义
****************************************************************************************/
typedef struct DeviceTabItem
{
	DEV_NO     iNo;			 ///< 设备index
	TDevice    *pDev;		 ///< 设备指针
} DeviceTabItem;



/***************************************************************************************
 * 私有变量声明、定义
****************************************************************************************/
#if 1
// ------------------------------------------------
// 1. 定义总线
// ------------------------------------------------
static TGpioBus         tGpioBus1("gpioBus1", 0xE000A000);  // General Purpose I/O
static TSpiBus          tSpi2Uart0("spi2Uart0",   "/dev/spi2uart0");
static TSpiBus          tSpi2Uart1("spi2Uart1",   "/dev/spi2uart1");

// ------------------------------------------------
// 2. 定义设备
// ------------------------------------------------
static TGpioFs          tGpio38("mio38", MIO38, OUTPUT, 1 /* 0: low,1: high */);
static TGpioFs          tGpio39("mio39", MIO39, INPUT,  2 /* 1: rising,2: falling */);

// static TRs232		tRs485A("rs485a");
static TRs232FromSpi	tRs485B("rs485b",   &tGpio39, &tSpi2Uart0, 0 /* 0: spi2Uart0 */);
static TRs232FromSpi	tRs232 ("rs232",    &tGpio39, &tSpi2Uart1, 1 /* 1: spi2Uart1 */);

// ------------------------------------------------
// 3. 设备表
// ------------------------------------------------
static const DeviceTabItem psDevices[DEV_NO_MAX + 1] =
	{
		{ DEV_NO_GPIO38,         &tGpio38 },
		{ DEV_NO_GPIO39,         &tGpio39 },

		{ DEV_NO_RS485A,          NULL    },
		{ DEV_NO_RS485B,         &tRs485B },
		{ DEV_NO_RS232,          &tRs232  },

		{ DEV_NO_MAX, NULL },  //not used
};
#endif




/***************************************************************************************
 * 全局函数声明、定义
****************************************************************************************/

// 初始化设备
// extern "C" int HwInit(DEV_NO id)
// {
// 	int iRet;
// 	TDevice *pDev = NULL;

// 	if ((id <= DEV_NO_MIN) || (id >= DEV_NO_MAX))
// 	{
// 		debug_error("id==%d,out of range[DEV_NO_MIN, DEV_NO_MAX] \r\n", id);
// 		return -1;
// 	}

// 	pDev = psDevices[id].pDev;
// 	if (NULL == pDev)
// 	{
// 		return -1;
// 	}

// 	iRet = pDev->Init();
// 	return (iRet);
// }

extern "C" int HwOpen  (DEV_NO id, void* pHandle)
{
	if (id >= DEV_NO_MAX)
	{
		debug_error("id==%d,out of range[0..DEV_NO_MAX] \r\n", id);
		return (-1);
	}

	TDevice *pDev = psDevices[id].pDev;
	if (NULL == pDev)
	{
		debug_error("psDevices[%d].pDev == null \r\n", id);
		return (-1);
	}

	int iRet;
	iRet = pDev->Open(pHandle);
	return (iRet);
}


extern "C" int HwClose (DEV_NO id, void* pHandle)
{
	if (id >= DEV_NO_MAX)
	{
		debug_error("id==%d,out of range[0..DEV_NO_MAX] \r\n", id);
		return (-1);
	}

	TDevice *pDev = psDevices[id].pDev;
	if (NULL == pDev)
	{
		debug_error("psDevices[%d].pDev == null \r\n", id);
		return (-1);
	}

	int iRet;
	iRet = pDev->Close(pHandle);
	return (iRet);
}


// 设备锁
extern "C" int HwLock(DEV_NO id)
{
	if (id >= DEV_NO_MAX)
	{
		debug_error("id==%d,out of range[0..DEV_NO_MAX] \r\n", id);
		return (-1);
	}

	TDevice *pDev = psDevices[id].pDev;
	if (NULL == pDev)
	{
		debug_error("psDevices[%d].pDev == null \r\n", id);
		return (-1);
	}

	int iRet;
	iRet = pDev->Lock();
	return (iRet);
}

// 设备开锁
extern "C" int HwUnlock(DEV_NO id)
{

	if (id >= DEV_NO_MAX)
	{
		debug_error("id==%d,out of range[0..DEV_NO_MAX] \r\n", id);
		return (-1);
	}

	TDevice *pDev = psDevices[id].pDev;
	if (NULL == pDev)
	{
		debug_error("psDevices[%d].pDev == null \r\n", id);
		return (-1);
	}

	int iRet;
	iRet = pDev->Unlock();
	if (0 > iRet)
	{
		debug_error("psDevices[%d]->Unlock() < 0 \r\n", id);
		return (-1);
	}

	return (0);
}

// 读数据
extern "C" int HwRead(DEV_NO id, long address, void *buf, long size)
{

	if (id >= DEV_NO_MAX)
	{
		debug_error("id==%d,out of range[0..DEV_NO_MAX] \r\n", id);
		return (-1);
	}

	TDevice *pDev =  psDevices[id].pDev;
	if (NULL == pDev)
	{
		return (-1);
	}

	int iRet;
	iRet = pDev->Read(address, buf, size);
	if (iRet < 0)
	{
		debug_error("BytesRead() < 0\n");
		return (-1);
	}
	return (iRet);
}

// 写数据
extern "C" int HwWrite(DEV_NO id, long address, void *buf, long size)
{

	if (id >= DEV_NO_MAX)
	{
		debug_error("id==%d,out of range[0..DEV_NO_MAX] \r\n", id);
		return (-1);
	}

	TDevice *pDev =  psDevices[id].pDev;
	if (NULL == pDev)
	{
		debug_error("psDevices[%d].pDev==NULL\n", id);
		return (-1);
	}

	int iRet;
	iRet = pDev->Write(address, buf, size);
	if (0 > iRet)
	{
		debug_error("0 > iRet\n");
		return (-1);
	}
	return (iRet);
}

// 设备控制
extern "C" int HwIoctl(DEV_NO id, long cmd, void *buf,  long *psize)
{

	if (id >= DEV_NO_MAX)
	{
		debug_error("id==%d,out of range[0..DEV_NO_MAX] \r\n", id);
		return (-1);
	}

	TDevice *pDev =  psDevices[id].pDev;
	if (NULL == pDev)
	{
		debug_error("psDevices[%d].pDev==NULL\n", id);
		return (-1);
	}

	int iRet;
	iRet = pDev->Ioctl(cmd, buf, psize);
	if (0 > iRet)
	{
		debug_error("Ioctl(cmd, buf, psize) < 0\n");
		return (-1);
	}

	return (0);
}


// 初始化全部设备
extern "C" int DevicesInit()
{
	TDevice *pSelf;
	for (int id = 0; id < DEV_NO_MAX; id++)
	{
		pSelf =  psDevices[id].pDev;
		if (NULL != pSelf)
		{
			int iRet = pSelf->Init();
			if (iRet < 0)
			{
				debug_error("psDevices[%d]->Init() < 0 \n", id);
				return (-1);
			}
		}
	}

	return (0);
}

